#include <gtest/gtest.h>
#include <iostream>
#include "../../server/mq_route.hpp"

class RouteTest : public ::testing::Environment
{
public:
    virtual void SetUp() override
    {
        
    }

    virtual void TearDown() override
    {

    }
};

TEST(RouteTest, isLegalRoutingKey)
{
    using namespace xzt;
    using std::string;

    string rkey_1 = "news.music.pop";
    string rkey_2 = "news..music.rock";
    string rkey_3 = "news.,music.rap";  // false
    string rkey_4 = "news.music.jazz_top100";

    EXPECT_TRUE(Router::isLegalRoutingKey(rkey_1));
    EXPECT_TRUE(Router::isLegalRoutingKey(rkey_2));
    EXPECT_FALSE(Router::isLegalRoutingKey(rkey_3));
    EXPECT_TRUE(Router::isLegalRoutingKey(rkey_4));
}

TEST(RouteTest, isLegalBindingKey)
{
    using namespace xzt;
    using std::string;

    string bkey_1 = "news.music.#";
    string bkey_2 = "news.#.rock";
    string bkey_3 = "news.#.#.rap"; // false
    string bkey_4 = "news.#.*.jazz"; // false
    string bkey_5 = "news.*.#.rap"; // false
    string bkey_6 = "news.*.*.pop";

    EXPECT_TRUE(Router::isLegalBindingKey(bkey_1));
    EXPECT_TRUE(Router::isLegalBindingKey(bkey_2));
    EXPECT_FALSE(Router::isLegalBindingKey(bkey_3));
    EXPECT_FALSE(Router::isLegalBindingKey(bkey_4));
    EXPECT_FALSE(Router::isLegalBindingKey(bkey_5));
    EXPECT_TRUE(Router::isLegalBindingKey(bkey_6));
}

TEST(RouteTest, route)
{
    using namespace xzt;
    using std::string;

    std::vector<string> binding_keys = {
        "aaa",
        "aaa.bbb",
        "aaa.bbb",
        "aaa.bbb",
        "aaa.#.bbb",
        "aaa.bbb.#",
        "#.bbb.ccc",
        "aaa.bbb.ccc",
        "aaa.*",
        "aaa.*.bbb",
        "*.aaa.bbb",
        "#",
        "aaa.#",
        "aaa.#",
        "aaa.#.ccc",
        "aaa.#.ccc",
        "aaa.#.ccc",
        "#.ccc",
        "#.ccc",
        "aaa.#.ccc.ccc",
        "aaa.#.bbb.*.bbb"};
    
    std::vector<string> routing_keys = {
        "aaa",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.ccc",
        "aaa.bbb.ccc",
        "aaa.ccc.bbb",
        "aaa.bbb.ccc.ddd",
        "aaa.bbb.ccc",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.bbb",
        "aaa.bbb.ccc",
        "aaa.ccc",
        "aaa.bbb.ccc",
        "aaa.aaa.bbb.ccc",
        "ccc",
        "aaa.bbb.ccc",
        "aaa.bbb.ccc.ccc.ccc",
        "aaa.ddd.ccc.bbb.eee.bbb"};

    std::vector<bool> results = {
        true,
        true,
        false,
        false,
        false,
        false,
        false,
        true,
        true,
        false,
        false,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true};

    ASSERT_EQ(binding_keys.size(), routing_keys.size());
    ASSERT_EQ(binding_keys.size(), results.size());

    for (size_t i = 0; i < binding_keys.size(); ++i)
    {
        DLOG("binding_key: %s, routing_key: %s", binding_keys[i].c_str(), routing_keys[i].c_str());
        ASSERT_EQ(Router::route(ExchangeType::TOPIC, routing_keys[i], binding_keys[i]), results[i]);
    }
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    ::testing::AddGlobalTestEnvironment(new RouteTest);
    return RUN_ALL_TESTS();
}